/*
 * ============================================================================
 *                   GNU Lesser General Public License
 * ============================================================================
 *
 *
 *
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
 *
 *
 *
 */
package rad.framework.seam;

import java.lang.reflect.Method;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import rad.framework.jsf.JsfUtil;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.jboss.seam.core.Expressions;
import org.jboss.seam.core.Expressions.ValueExpression;

public class ActionMetadata {
	
	protected static final String MESSAGES_PREFIX = "#{messages['";
	protected static final String LABEL_SUFFIX = "label']}";
	protected static final String TITLE_SUFFIX = "title']}";
	protected static final String ICON_ACTIVE_SUFFIX = "icon_active']}";
	protected static final String ICON_ENABLED_SUFFIX = "icon_enabled']}";
	protected static final String ICON_DISABLED_SUFFIX = "icon_disabled']}";
			
	private String value;
	private ValueExpression<String> label;
	private ValueExpression<String> title;
	private ValueExpression<String> iconActive;
	private ValueExpression<String> iconEnabled;
	private ValueExpression<String> iconDisabled;

	private ValueExpression<Boolean> rendered;	
	private ValueExpression<Boolean> disabled;
	private Integer sort;
	
	private Boolean immediate;
	
	// TODO stereotype...

	public ActionMetadata(String value, int sort, String[] prefixes,
			String rendered, String disabled, Boolean immediate) {
		this.value = value;
		this.sort = sort;
		this.immediate = immediate;
		
		if (rendered != null) {
			this.rendered = Expressions.instance().createValueExpression(
					rendered, Boolean.class);
		}
		
		if (disabled != null) {
			this.disabled = Expressions.instance().createValueExpression(
					disabled, Boolean.class);
		}
		
		String prefix = MESSAGES_PREFIX + getPrefix(prefixes, value);
		this.label = Expressions.instance().createValueExpression(
				prefix + LABEL_SUFFIX, String.class);
		this.title = Expressions.instance().createValueExpression(
				prefix + TITLE_SUFFIX, String.class);
		this.iconActive = Expressions.instance().createValueExpression(
				prefix + ICON_ACTIVE_SUFFIX, String.class);
		this.iconEnabled = Expressions.instance().createValueExpression(
				prefix + ICON_ENABLED_SUFFIX, String.class);
		this.iconDisabled = Expressions.instance().createValueExpression(
				prefix + ICON_DISABLED_SUFFIX, String.class);
	}
	
	public ActionMetadata(Method method, Action annotation, int sort, String... prefixes) {
		this(method.getName(), annotation.sort() == 0 ? sort : annotation
				.sort(), annotation.prefixes().length == 0 ? prefixes
				: annotation.prefixes(), annotation.rendered(), annotation
				.disabled(), annotation.immediate());
	}
	
	public ActionMetadata(Method method, Action annotation, int sort) {
		this(method.getName(), annotation.sort() == 0 ? sort : annotation
				.sort(), annotation.prefixes(), annotation.rendered(),
				annotation.disabled(), annotation.immediate());
	}

	protected String getPrefix(String[] prefixes, String name) {
		StringBuilder builder = new StringBuilder();
		for (String string : prefixes) {
			builder.append(string.replace(" ", ""));
			builder.append("_");
		}
		builder.append(name);
		builder.append("_");
		return builder.toString();
	}

	public String getValue() {
		return value;
	}

	public Integer getSort() {
		return sort;
	}

	public void setSort(Integer sort) {
		this.sort = sort;
	}

	public String getLabel() {
		if (label == null) return null;
		return label.getValue();
	}

	public String getTitle() {
		if (title == null) return null;
		return title.getValue();
	}

	public String getIcon() {
		if (isActive()) {
			return iconActive.getValue();
		} else if (isDisabled()) {
			return iconDisabled.getValue();
		} else {
			return iconEnabled.getValue();
		}
	}

	public boolean isActive() {
		return false;
	}

	public boolean isRendered() {
		return JsfUtil.getValue(rendered, true);
	}

	public boolean isDisabled() {
		if (isActive()) {
			return true;
		} else {
			return JsfUtil.getValue(disabled, false);
		}
	}

	public Boolean getImmediate() {
		return immediate;
	}
	
	public static void sort(List<ActionMetadata> actions) {
		Collections.sort(actions, new Comparator<ActionMetadata>() {
			public int compare(ActionMetadata lh, ActionMetadata rh) {
				int comp = lh.getSort().compareTo(rh.getSort());
				return (comp != 0 ? comp : lh.getValue().compareTo(
						rh.getValue()));
			}
		});
	}

	public String toString() {
		ToStringBuilder builder = new ToStringBuilder(this,
				ToStringStyle.MULTI_LINE_STYLE);
		builder.append("value", value);
		builder.append("label", label.getExpressionString());
		builder.append("title", title.getExpressionString());
		builder.append("iconActive", iconActive.getExpressionString());
		builder.append("iconEnabled", iconEnabled.getExpressionString());
		builder.append("iconDisabled", iconDisabled.getExpressionString());
		builder.append("rendered", rendered.getExpressionString());
		builder.append("disabled", disabled.getExpressionString());
		builder.append("sort", sort);
		builder.append("immediate", immediate);
		return builder.toString();
	}
}